package vista;

import interfasesEdificio.GeneradorCiviles;
import interfasesEdificio.GeneradorUnidades;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.Observable;
import java.util.Observer;

import javax.swing.DefaultListModel;
import javax.swing.ListSelectionModel;

import colaDeProduccion.ColaDeProduccion;
import colaDeProduccion.Producto;

import mapas.Region;
import clasesGenerales.Conjunto;
import control.generarUnidad.CambioSeleccionListener;
import control.generarUnidad.botonGenerarListener;
import control.juego.ControladorSeleccion;
import control.ronda.controladorFinTurno;
import edificios.Edificio;

/**
 * @author Grupo 2, Algoritmos y programacion 3, Catedra Fontela<br>1er cuat 2007    
 * <br> Esta clase se encarga de representar la vista para generar unidades.
 */

public class VistaGenerarUnidad extends VentanaConDosListas implements Observer,CerrablePorFinTurno{

	//Modelo
	private Region region;
	private ColaDeProduccion colaEdificio;
	private int cantEdificios;
	
	private static String subtitulo1 = "Edificio generador ";
	private static String subtitulo2 = "Cola de Produccion ";
	private static String accion = "Generar";
	
	private static VistaGenerarUnidad Instance = null;
	
	/**
	 * Se encarga de inicializar la vista para generar unidades.
	 * @param titulo Titulo de la ventana
	 */
	private VistaGenerarUnidad(String titulo){
		//Llamo al constructor del padre
		super(titulo, subtitulo1, subtitulo2, accion);
		//agrego la funcionalidad a los botones
		this.ActivarComportamientoBotonAccion();
		this.ActivarComportamientoBotonSalir();
		//agrego un escuchador de cambios de seleccion
		this.getLista1().getSelectionModel().addListSelectionListener(new CambioSeleccionListener(this));
		this.getLista1().setSelectedIndex(0);
		//conecto con la instancia
		Instance = this;
		//agrego la instancia como cerrable por fin de turno
		controladorFinTurno.getInstance().agregarVistaCerrable(this);
	}
	
	/**
	 * @return La unica instancia de la VistaGenerarUnidad
	 */
	public static VistaGenerarUnidad getInstance(){
		if(Instance == null)
			 new VistaGenerarUnidad(" - CREAR UNIDAD - ");
		Instance.actualizarModelo();
		return Instance;
	}
	
	/**
	 * Notifica a la vista de los cambios de seleccion de regiones
	 */
	private void actualizarModelo() {
		String titulo = " - CREAR UNIDAD EN ";
		if(region!=null){
			region.deleteObserver(this);
			borrarObservadoresEdificios(region);
		}
		//Conecto con el modelo
		this.region = ControladorSeleccion.GetInstance().getSlot1();
		this.colaEdificio = null;
		//agrego esta vista como observadora del modelo
		if (region!=null){
			region.addObserver(this);
			titulo += region.getNombre();
		} else
			titulo += "NINGUNA";
		titulo += " - ";
		this.setTitle(titulo);
		this.cantEdificios = -1; //Reseteo la cantidad de edificios
		this.update(null,null);
	}
	
	/**
	 * Establece los modos de seleccion de las listas.
	 */
	protected void establecerModosDeSeleccion(){
		getLista1().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		getLista2().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
	}
	
	/**
	 * Se encarga de actualizar la vista, cuando el modelo cambie
	 */
	public void update(Observable arg0, Object arg1) {
		//Remuevo todos los elementos de la lista de cola de prod
		this.getModelo2().removeAllElements();
		//Si la region no es nula
		if (region != null){
			//Si la cantidad de edificios cambio, cargo nuevamente los edificios
			if (this.cantEdificios != region.getEdificios().getCantidadElementos()){
				this.getModelo1().removeAllElements();
				CargarEdificios(this.getModelo1(), region);
				this.cantEdificios = region.getEdificios().getCantidadElementos();
			}
			//Cargo los productos de la cola de prod
			CargarProductos(this.getModelo2(), colaEdificio);
		}
	}

	/**
	 * Carga los edificios de una region en un modelo de lista
	 * @param modeloLista Modelo donde cargar los edificios
	 * @param region Region que contiene a los edificios
	 */
	private void CargarEdificios(DefaultListModel modeloLista, Region region){
		//Obtengo los edificios
		Conjunto edificios = region.getEdificios();
		//Monto un iterador y recorro los elementos
		Iterator iterador = edificios.iterator();
		while (iterador.hasNext()){
			//Obtengo cada edificio y lo agrego al modelo de la lista
			Edificio edificio = (Edificio) iterador.next();
			//Si puede generar unidades no civiles lo agrego
			if ((edificio instanceof GeneradorUnidades) && !(edificio instanceof GeneradorCiviles)){
				modeloLista.addElement(edificio);
				edificio.addObserver(this);
			}
		}
	}
	/**
	 * Carga los productos de la cola de produccion del edificio, en la lista
	 * @param modeloLista modelo de la lista donde cargar los productos
	 * @param cola Cola de produccion
	 */
	private void CargarProductos(DefaultListModel modeloLista, ColaDeProduccion cola){
		try{
		//Obtengo los productos
		ArrayList productos = cola.getProductos();
		//Monto un iterador y recorro los elementos
		Iterator iterador = productos.iterator();
		while (iterador.hasNext()){
			//Obtengo cada producto, extraigo el contenido y lo agrego al modelo de la lista
			Producto producto = (Producto) iterador.next();
			modeloLista.addElement(producto);
			producto.addObserver(this);
		}
		} catch (NullPointerException e){}
	}
	/**
	 * Saca como observadora esta vista de los edificios de una region
	 * @param region Region que contiene a los edificios
	 */
	private void borrarObservadoresEdificios(Region region){
		//Obtengo los edificios
		Conjunto edificios = region.getEdificios();
		//Monto un iterador y recorro los elementos
		Iterator iterador = edificios.iterator();
		while (iterador.hasNext()){
			//Obtengo cada edificio y le saco esta vista como observadora
			Edificio edificio = (Edificio) iterador.next();
			//Si puede generar unidades no civiles
			if ((edificio instanceof GeneradorUnidades) && !(edificio instanceof GeneradorCiviles))
				edificio.deleteObserver(this);
		}
	}
	/**
	 * Saca esta vista como observadora de los productos de la cola de produccion del edificio
	 * @param cola Cola de produccion
	 */
	private void borrarObservadoresProductosEnCola(ColaDeProduccion cola){
		try{
		//Obtengo los productos
		ArrayList productos = cola.getProductos();
		//Monto un iterador y recorro los elementos
		Iterator iterador = productos.iterator();
		while (iterador.hasNext()){
			//Obtengo cada producto y extraigo esta vista como observadora del mismo
			Producto producto = (Producto) iterador.next();
			producto.deleteObserver(this);
		}
		} catch (NullPointerException e){}
	}
	/**
	 * @return La region donde se generan unidades
	 */
	public Region getRegion(){
		return this.region;
	}
	/**
	 * @return La cola de edificio observada por esta vista
	 */
	public ColaDeProduccion getColaEdificio(){
		return this.colaEdificio;
	}
	/**
	 * Setea una nueva cola de edificio a la vista
	 * @param cola Cola de edifico a agregar
	 */
	public void SetColaEdificio (ColaDeProduccion cola){
		if (this.colaEdificio != null){
			this.colaEdificio.deleteObserver(this);
			borrarObservadoresProductosEnCola(this.colaEdificio);
		}
		this.colaEdificio = cola;
		if (cola != null)
			cola.addObserver(this);
	}
	/**
	 * Activa el comportamiento del boton accion.
	 * Le asigna la accion de Generar Unidad.
	 */
	protected void ActivarComportamientoBotonAccion(){
		this.getBotonAccion().addActionListener(new botonGenerarListener(this));
	}

	public void CerrarVentana() {
		this.setVisible(false);
		
	}
}

